package com.lyn.serialPort;

/**
 * @author:longyongning
 * @date:2021/10/2
 * @description:串口校验工具类
 */
public class CheckUtil {
    /**
     * 校验校验码是否一致
     *
     * @param type     需要使用的校验规则
     * @param bytes    待生成校验码的字节数组
     * @param code     待匹配的校验码字节数组
     * @param changeGD 是否高低位转换，true低位在前高位在后，false高位在前低位在后
     * @return true校验一致
     */
    public static boolean checkVerification(int type, byte[] bytes, byte[] code, boolean changeGD) {
        switch (type) {
            case 10:
                byte b = andVerification(bytes);
                if (b == code[0])
                    return true;
                else
                    return false;
            case 11:
                byte[] b1 = crcVerification(bytes, changeGD);
                if (b1[0] == code[0] && b1[1] == code[1])
                    return true;
                else
                    return false;
            case 12:
                byte b2 = orVerification(bytes);
                if (b2 == code[0])
                    return true;
                else
                    return false;
            case 13:
                byte b3 = complement(bytes);
                if (b3 == code[0])
                    return true;
                else
                    return false;
            default:
                return false;
        }
    }

    /**
     * 异或校验，返回一个字节
     *
     * @param bytes 待计算校验的字节数组
     * @return 校验码
     */
    public static byte orVerification(byte[] bytes) {
        int nAll = 0;
        for (int i = 0; i < bytes.length; i++) {
            int nTemp = bytes[i];
            nAll = nAll ^ nTemp;
        }
        return (byte) nAll;
    }

    /**
     * 和校验，所有数据求和后%256 ，返回一个字节
     *
     * @param bytes 待计算校验的字节数组
     * @return 校验码
     */
    public static byte andVerification(byte[] bytes) {
        int iSum = 0;
        for (int i = 0; i < bytes.length; i++) {
            iSum += bytes[i];
        }
        iSum %= 0x100;
        return (byte) iSum;
    }

    /**
     * CRC校验，返回两个字节
     *
     * @param bytes    待计算校验的字节数组
     * @param changeGD 是否转换高低位，true低位在前高位在后，false高位在前低位在后
     * @return 校验码
     */
    public static byte[] crcVerification(byte[] bytes, boolean changeGD) {
        int CRC = 0x0000ffff;
        int POLYNOMIAL = 0x0000a001;

        int i, j;
        for (i = 0; i < bytes.length; i++) {
            CRC ^= (int) bytes[i];
            for (j = 0; j < 8; j++) {
                if ((CRC & 0x00000001) == 1) {
                    CRC >>= 1;
                    CRC ^= POLYNOMIAL;
                } else {
                    CRC >>= 1;
                }
            }
        }
        if (changeGD) {
            CRC = ((CRC & 0x0000FF00) >> 8) | ((CRC & 0x000000FF) << 8);
        }
        return String.valueOf(CRC).getBytes();
    }

    /**
     * 补码求和校验，返回一个字节
     *
     * @param bytes 待计算校验的字节数组
     * @return 校验码
     */
    public static byte complement(byte[] bytes) {
        int iSum = 0;
        for (int i = 0; i < bytes.length; i++) {
            iSum += bytes[i];
        }
        iSum = 256 - iSum;
        return (byte) iSum;
    }

}
